<?php
/**
 * 
 * Entity Agent for storig and managing agent operations.
 * @author udit
 *
 */
class Reale_Model_Users_Agent
{
    /**
     * 
     * Stores agent's identification number
     * @var int
     */
    protected $_agent_id;
    /**
     * 
     * Stores agent's registration number
     * @var int
     */
    protected $_agent_reg_id;
    /**
     * 
     * Stores agent's name
     * @var string
     */
    protected $_agent_name;
    /**
     * 
     * Stores agent's father's name
     * @var string
     */
    protected $_father_name;
    /**
     * 
     * Stores agent's husband's name (if applicable)
     * @var string
     */
    protected $_husband_name;
    /**
     * 
     * Stores agent's mother's name
     * @var string
     */
    protected $_mother_name;
    /**
     * 
     * Stores agent's mobile number
     * @var string
     */
    protected $_mobile_no;
    /**
     * 
     * Stores agent's alternate number
     * @var string
     */
    protected $_alternate_no;
    /**
     * 
     * Stores agent's rgrn date
     * @var string
     */
    protected $_rgrn_date;
    /**
     * 
     * Stores agent's date of birth
     * @var string
     */
    protected $_dob;
    /**
     * 
     * Stores agent's gender 
     * M => Male
     * F => Female
     * @var string|char
     */
    protected $_gender_id;
    /**
     * 
     * Stores agent's nationality_id id
     * IND => Indian 
     * etc...
     * @var string
     */
    protected $_nationality_id;
    /**
     * 
     * Stores agent's marital status
     * S => Single
     * M => Married
     * D => Divorsed
     * SP => Seperated
     * @var string|char
     */
    protected $_marital_status_id;
    /**
     * 
     * Stores agent's type
     * IDVL => Indiviudual
     * COMP => Company
     * PART => Partnership
     * PROP => Proprietorship
     * @var string
     */
    protected $_applicant_type_id;
    /**
     * 
     * Stores agent's type
     * Like company or dealership name
     * Like property dealer's business name.
     */
    protected $_agent_type_spec;
    /**
     * 
     * Stores agent's activity status
     * A => Active
     * S => Semi Active
     * N => Not Active
     * @var string|char;  
     */
    protected $_activity_status;
    /**
     * 
     * Stores business level of agent
     * 1 => Business Associate
     * 2 => etc....
     * @var string|int;
     */
    protected $_business_level;
    /**
     * 
     * Stores agent's PAN number
     * @var string 
     */
    protected $_pan;
    /**
     * 
     * Stores agent's email address
     * @var string 
     */
    protected $_email;
    /**
     * 
     * Stores agent's occupation
     * @var string 
     */
    protected $_occupation;
    /**
     * 
     * Stores agent's permanent address
     * @var Reale_Model_Location
     */
    protected $_paddress;
    /**
     * 
     * Stores agent's communication/coresspondance address
     * @var Reale_Model_Location
     */
    protected $_caddress;
    /**
     * 
     * Stores agent's sponsor
     * @var string|Reale_Model_Users_Agent
     */
    protected $_sponsor;
    /**
     * 
     * Stores agent's nominee
     * @var Reale_Model_Users_Nominee
     */
    protected $_nominee;
    /**
     * 
     * Stores agent's password
     * @var string
     */
    protected $_password;
    /**
     * 
     * Stores agent entity mapper
     * @var Reale_Model_Users_AgentMapper
     * 
     */
    protected $_mapper;
    protected $_valid;
    protected $_cansponsor;
    const ROOT_AGENT_REG = 'AGNT-A-0';
    const ROOT_AGENT_ID = '1';
    const MAX_SPONSOR = 5;
    const AGENT_REG_FEES = 10000;
    const MAX_UPLINE = 10;
    /**
     * 
     * Array define brokerage for agent registration profit distribution.
     * Key => Value pair.
     * Key = defines static node level of the agent 
     * Value = defines the brokerage percentage.
     * @var array $_networkBrokerage
     */
    static $_networkBrokerage  = ARRAY(
    								 '1'=> '0',
    								 '2'=>'15',
    								 '3'=>'20',
    								 '4'=>'25',
    								 '5'=>'30',
    								 '6'=>'32',
    								 '7'=>'34',
    								 '8'=>'36',
    								 '9'=>'38',
    								 '10'=>'40'
    								);
    /**
     * Constructor
     * 
     * @param  array|null $options 
     * @return void
     */
    public function __construct (array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
        /*
        if (isset($options['agent_reg_id'])) {
            self::isValid();
        }*/
    }
    /**
     * Overloading: allow property access
     * 
     * @param  string $name 
     * @param  mixed $value 
     * @return void
     */
    public function __set ($name, $value)
    {
        $method = 'set' . ucfirst($name);
        if ('mapper' == $name || ! method_exists($this, $method)) {
            throw new Exception('Invalid property specified', Zend_Log::DEBUG);
        }
        $this->$method($value);
    }
    /**
     * Overloading: allow property access
     * 
     * @param  string $name 
     * @return mixed
     */
    public function __get ($name)
    {
        $method = 'get' . ucfirst($name);
        if ('mapper' == $name || ! method_exists($this, $method)) {
            throw new Exception('Invalid property specified. :'.$method, Zend_Log::DEBUG);
        }
        return $this->$method();
    }
    /**
     * Set state
     * 
     * @param  array $options 
     * @return Reale_Model_Users_Agent
     */
    public function setOptions (array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }
    /**
     * 
     * Setter for agent_id 
     * @param int $agent_id
     * @return Reale_Model_Users_Agent
     */
    public function setAgent_id ($agent_id)
    {
        $this->_agent_id = $agent_id;
        return $this;
    }
    /**
     * 
     * Getter for agent_id
     * @return int $_agent_id
     */
    public function getAgent_id ()
    {
        if (! isset($this->_agent_id)) {
            self::_fetchAgentId();
        }
        return $this->_agent_id;
         //throw new Exception('The objects primary key(i.e. $_agent_id) is not set.',Zend_Log::WARN); 
    }
    /**
     * @return the $_agent_reg_id
     */
    public function getAgent_reg_id ()
    {
        if (! isset($this->_agent_reg_id)) {
            self::_fetchRegistrationId();
        }
        return $this->_agent_reg_id;
    }
    /**
     * @param int $_agent_reg_id
     */
    public function setAgent_reg_id ($_agent_reg_id)
    {
        $this->_agent_reg_id = $_agent_reg_id;
    }
    /**
     * 
     * Setter for agent_name 
     * @param string $agent_name
     * @return Reale_Model_Users_Agent
     */
    public function setAgent_name ($agent_name)
    {
        $this->_agent_name = $agent_name;
        return $this;
    }
    /**
     * 
     * Getter for agent_name
     * @return string $_agent_name
     */
    public function getAgent_name ()
    {
        return $this->_agent_name;
    }
    /**
     * 
     * Setter for father_name 
     * @param string $father_name
     * @return Reale_Model_Users_Agent
     */
    public function setFather_name ($father_name)
    {
        $this->_father_name = $father_name;
        return $this;
    }
    /**
     * 
     * Getter for father_name
     * @return string $_father_name
     */
    public function getFather_name ()
    {
        return $this->_father_name;
    }
    /**
     * 
     * Setter for husband_name (if applicable) 
     * @param string $husband_name
     * @return Reale_Model_Users_Agent
     */
    public function setHusband_name ($husband_name)
    {
        $this->_husband_name = $husband_name;
        return $this;
    }
    /**
     * 
     * Getter for husband_name (if applicable)
     * @return string $_husband_name
     */
    public function getHusband_name ()
    {
        return $this->_husband_name;
    }
    /**
     * 
     * Setter for mother_name 
     * @param string $mother_name
     * @return Reale_Model_Users_Agent
     */
    public function setMother_name ($mother_name)
    {
        $this->_mother_name = $mother_name;
        return $this;
    }
    /**
     * 
     * Getter for mother_name
     * @return string $_mother_name
     */
    public function getMother_name ()
    {
        return $this->_mother_name;
    }
    /**
     * 
     * Setter for mobile number 
     * @param string $mobile_number
     * @return Reale_Model_Users_Agent
     */
    public function setMobile_no ($mobile_no)
    {
        $this->_mobile_no = $mobile_no;
        return $this;
    }
    /**
     * 
     * Getter for mobile number
     * @return string $_mobile_no
     */
    public function getMobile_no ()
    {
        return $this->_mobile_no;
    }
    /**
     * 
     * Setter for alternate number 
     * @param string $alternate_no
     * @return Reale_Model_Users_Agent
     */
    public function setAlternate_no ($alternate_no)
    {
        $this->_alternate_no = $alternate_no;
        return $this;
    }
    /**
     * 
     * Getter for alternate number
     * @return string $_alternate_no
     */
    public function getAlternate_no ()
    {
        return $this->_alternate_no;
    }
    /**
     * 
     * Setter for registration date 
     * @param string $rgrn_date
     * @return Reale_Model_Users_Agent
     */
    public function setRgrn_date ($rgrn_date)
    {
        $this->_rgrn_date = $rgrn_date;
        return $this;
    }
    /**
     * 
     * Getter for registration date 
     * @return string $_rgrn_date
     */
    public function getRgrn_date ()
    {
        return $this->_rgrn_date;
    }
    /**
     * 
     * Setter for date of birth 
     * @param string $dob
     * @return Reale_Model_Users_Agent
     */
    public function setDob ($dob)
    {
        $this->_dob = $dob;
        return $this;
    }
    /**
     * 
     * Getter for date of birth 
     * @return string $_dob
     */
    public function getDob ()
    {
        return $this->_dob;
    }
    /**
     * 
     * Setter for gender 
     * @param string|char $gender_id
     * @return Reale_Model_Users_Agent
     */
    public function setGender_id ($gender_id)
    {
        $this->_gender_id = $gender_id;
        return $this;
    }
    /**
     * 
     * Getter for gender 
     * @return string|char $_gender_id
     */
    public function getGender_id ()
    {
        return $this->_gender_id;
    }
    /**
     * 
     * Setter for nationality_id 
     * @param string $nationality_id
     * @return Reale_Model_Users_Agent
     */
    public function setNationality_id ($nationality_id)
    {
        $this->_nationality_id = $nationality_id;
        return $this;
    }
    /**
     * 
     * Getter for nationality_id 
     * @return string $_nationality_id
     */
    public function getNationality_id ()
    {
        return $this->_nationality_id;
    }
    /**
     * 
     * Setter for marital_status_id 
     * @param string|char $marital_status_id
     * @return Reale_Model_Users_Agent
     */
    public function setMarital_status_id ($marital_status_id)
    {
        $this->_marital_status_id = $marital_status_id;
        return $this;
    }
    /**
     * 
     * Getter for marital_status_id 
     * @return string|char $_marital_status_id
     */
    public function getMarital_status_id ()
    {
        return $this->_marital_status_id;
    }
    /**
     * 
     * Setter for applicant_type_id 
     * @param string $applicant_type_id
     * @return Reale_Model_Users_applicant
     */
    public function setApplicant_type_id ($applicant_type_id)
    {
        $this->_applicant_type_id = $applicant_type_id;
        return $this;
    }
    /**
     * 
     * Getter for applicant_type_id 
     * @return string $_applicant_type_id
     */
    public function getApplicant_type_id ()
    {
        return $this->_applicant_type_id;
    }
    /**
     * 
     * Setter for activity_status 
     * @param string $activity_status
     * @return Reale_Model_Users_Agent
     */
    public function setActivity_status ($activity_status)
    {
        $this->_activity_status = $activity_status;
        return $this;
    }
    /**
     * 
     * Getter for activity_status 
     * @return string $_activity_status
     */
    public function getActivity_status ()
    {
        return $this->_activity_status;
    }
    /**
     * 
     * Setter for business_level 
     * @param string $business_level
     * @return Reale_Model_Users_Agent
     */
    public function setBusiness_level ($business_level)
    {
        $this->_business_level = $business_level;
        return $this;
    }
    /**
     * 
     * Getter for business_level 
     * @return string $_business_level
     */
    public function getBusiness_level ()
    {
        return $this->_business_level;
    }
    /**
     * 
     * Setter for pan 
     * @param string $pan
     * @return Reale_Model_Users_Agent
     */
    public function setPan ($pan)
    {
        $this->_pan = $pan;
        return $this;
    }
    /**
     * 
     * Getter for pan 
     * @return string $_pan
     */
    public function getPan ()
    {
        return $this->_pan;
    }
    /**
     * 
     * Setter for email 
     * @param string $email
     * @return Reale_Model_Users_Agent
     */
    public function setEmail ($email)
    {
        $this->_email = $email;
        return $this;
    }
    /**
     * 
     * Getter for email 
     * @return string $_email
     */
    public function getEmail ()
    {
        return $this->_email;
    }
    /**
     * 
     * Setter for occupation 
     * @param string $occupation
     * @return Reale_Model_Users_Agent
     */
    public function setOccupation ($occupation)
    {
        $this->_occupation = $occupation;
        return $this;
    }
    /**
     * 
     * Getter for occupation 
     * @return string $_occupation
     */
    public function getOccupation ()
    {
        return $this->_occupation;
    }
    /**
     * 
     * Setter for paddress 
     * @param Reale_Model_Location $paddress
     * @return Reale_Model_Users_Agent
     */
    public function setPaddress (Reale_Model_Location $paddress)
    {
        $this->_paddress = $paddress;
        return $this;
    }
    /**
     * 
     * Getter for paddress 
     * @return string|Reale_Model_Location 
     */
    public function getPaddress ()
    {
        return $this->_paddress;
    }
    /**
     * 
     * Setter for Caddress 
     * @param Reale_Model_Location $caddress
     * @return Reale_Model_Users_Agent
     */
    public function setCaddress (Reale_Model_Location $caddress)
    {
        $this->_caddress = $caddress;
        return $this;
    }
    /**
     * 
     * Getter for caddress 
     * @return string|Reale_Model_Location 
     */
    public function getCaddress ()
    {
        return $this->_caddress;
    }
    /**
     * 
     * Setter for sponsor 
     * @param string|Reale_Model_Users_Agent $sponsor
     * @return Reale_Model_Users_Agent
     */
    public function setSponsor (Reale_Model_Users_Agent $sponsor)
    {
        $this->_sponsor = $sponsor;
        return $this;
    }
    /**
     * 
     * Getter for sponsor 
     * @return string|Reale_Model_Users_Agent 
     */
    public function getSponsor ()
    {
        return $this->_sponsor;
    }
    /**
     * 
     * Setter for agent_nominee
     * @param Reale_Model_Users_Nominee $nominee
     * @return Reale_Model_Users_Agent
     */
    public function setNominee (Reale_Model_Users_Nominee $nominee)
    {
        $this->_nominee = $nominee;
        return $this;
    }
    /**
     * 
     * Getter for agent_nominee
     * @return Reale_Model_Users_Nominee
     */
    public function getNominee ()
    {
        return $this->_nominee;
    }
    /**
     * 
     * Setter for password 
     * @param string $password
     * @return Reale_Model_Users_Agent
     */
    public function setPassword ($password)
    {
        $this->_password = $password;
        return $this;
    }
    /**
     * 
     * Getter for password 
     * @return string $_password
     */
    public function getPassword ()
    {
        return $this->_password;
    }
    /**
     * @return the $_agent_type_spec
     */
    public function getAgent_type_spec ()
    {
        return $this->_agent_type_spec;
    }
    /**
     * @param field_type $_agent_type_spec
     */
    public function setAgent_type_spec ($_agent_type_spec)
    {
        $this->_agent_type_spec = $_agent_type_spec;
    }
    /**
     * 
     * Setter function for agent mapper 
     * @param Reale_Model_Users_AgentMapper $mapper
     * @return Reale_Model_Users_Agent
     */
    public function setMapper ($mapper)
    {
        $this->_mapper = $mapper;
        return $this;
    }
    /**
     * 
     * Getter function for agent mapper
     * @return Reale_Model_Users_AgentMapper $_mapper
     */
    public function getMapper ()
    {
        if (null === $this->_mapper) {
            $this->setMapper(new Reale_Model_Users_AgentMapper());
        }
        return $this->_mapper;
    }
    /**
     * 
     * To save new or update existing agent's informtion.
     * return Reale_Model_Users_Agent | null
     * 
     */
    public function save ()
    {
        $return = $this->getMapper()->save($this);
        if ($return) {
            if ($return instanceof Reale_Model_Users_Agent) {
                $this->setAgent_id($return->getAgent_id());
            }
            return true;
        }
        return null;
    }
    /**
     * 
     * To save delete existing agent's informtion.
     * return Reale_Model_Users_Agent | null
     * 
     */
    public function delete ()
    {
        return $this->getMapper()->delete($this);
    }
    
    public function getProfile ()
    {
        $query = 'SELECT
    				`agent`.`agent_reg_id`
    				, `agent`.`agent_name`
    				, `agent`.`father_name`
    				, `agent`.`husband_name`
    				, `agent`.`mother_name`
    				, `agent`.`mobile_no`
    				, `agent`.`alternate_no`
    				, `agent`.`rgrn_date`
    				, `agent`.`dob`
    				, `agent`.`applicant_type_id`
    				, `agent`.`gender_id`
    				, `agent`.`nationality_id`
    				, `agent`.`pan`
    				, `agent`.`marital_status_id`
    				, `agent`.`email`
    				, `agent`.`occupation`
    				, `agent`.`agent_type_spec`
    				, `agent_nominee`.`nominee_name` AS nname
    				, `agent_nominee`.`relation` AS nrelation
    				, `agent_nominee`.`pan` AS npan
    				, `agent_nominee`.`address` AS naddress
    				, `agent_nominee`.`district` AS ndistrict
    				, `agent_nominee`.`place` AS nplace
    				, `agent_nominee`.`state` AS nstate
    				, `agent_nominee`.`postalcode` AS npostalcode
    				, `agent_address`.`paddress`
    				, `agent_address`.`pplace`
    				, `agent_address`.`pdistrict`
    				, `agent_address`.`pstate`
    				, `agent_address`.`ppostalcode`
    				, `agent_address`.`caddress`
    				, `agent_address`.`cplace`
    				, `agent_address`.`cdistrict`
    				, `agent_address`.`cstate`
    				, `agent_address`.`cpostalcode`
				FROM	
    				`agent_nominee`
    			INNER JOIN `agent` 
       				 ON (`agent_nominee`.`agent_id` = `agent`.`agent_id`)
    			INNER JOIN `agent_address` 
        	   		 ON (`agent_address`.`agent_id` = `agent`.`agent_id`)
				WHERE (`agent`.`agent_id` =?);';
        $bind = array($this->getAgent_id());
    	
//    	$this->setAgent_id($result["agent_id"])
//    		  ->setAgent_name($result["agent_name"])
//    		  ->setFather_name($result["father_name"])
//    		  ->setMother_name($result["mother_name"])
//    		  ->setHusband_name($result["husband_name"])
//    		  ->setMobile_no($result["mobile_no"])
//    		  ->setAlternate_no($result["alternate_no"])
//    		  ->setRgrn_date($result["rgrn_date"])
//    		  ->setDob($result["dob"])
//    		  ->setApplicant_type_id($result["applicant_type_id"])
//    		  ->setNationality_id($result["nationality_id"])
//    		  ->setMarital_status_id($result["marital_status"])
//    		  ->setPan($result["pan"])
//    		  ->setEmail($result["email"])
//    		  ->setAgent_type_spec($result["agent_type_spec"]);
		$dbTable = new Reale_Model_DbTable_Agent();
		
    	return $dbTable->getDefaultAdapter()->query($query,$bind)->fetch();
    }
    
    public function canSponsor ()
    {
        $sql = 'SELECT
                    COUNT(`sponsor_id`)
                FROM
                    `agent_network`
                WHERE (`sponsor_id`  = ?)';
        $bind = array($this->getAgent_id());
        $earnings = new Reale_Model_DbTable_Agent();
        $sponsored = $earnings->getDefaultAdapter()
            ->query($sql, $bind)
            ->fetchColumn();
        if (self::ROOT_AGENT_REG == $this->getAgent_reg_id()) {
            return $sponsored;
        } else 
            if ($sponsored < self::MAX_SPONSOR) {
                return $sponsored;
            } else {
                throw new Exception(
                $this->getAgent_reg_id() . ' has already sponsored ' . $sponsored .
                 ' agents.', Zend_Log::ERR);
            }
    }
    public function sponsor (Reale_Model_Users_Agent $agent)
    {
        $canSponsor = self::canSponsor();
        if (isset($canSponsor)) {
            $nodeLevel = self::fetchNodeLevel();
            $earnings = new Reale_Model_DbTable_AgentNetwork();
            $key = $earnings->insert(
            array('agent_id' => $agent->getAgent_id(), 
            'sponsor_id' => $this->getAgent_id(), 'node_level' => $nodeLevel + 1));
            try {
                self::canSponsor();
            } catch (Exception $e) {
                $this->getMapper()->updateBusinessTree($this);
            }
            return $key;
        }
    }
    /**
     * 
     * @return int
     */
    public function fetchNodeLevel ()
    {
        $sql = 'SELECT `agent_network`.`node_level`
        		FROM `agent_network` 
        		WHERE `agent_network`.`agent_id`= ?';
        $bind = array($this->getAgent_id());
        $earnings = new Reale_Model_DbTable_AgentNetwork();
        return $earnings->getDefaultAdapter()
            ->query($sql, $bind)
            ->fetchColumn();
    }
    protected function _fetchAgentId ()
    {
        if (is_null(self::getAgent_reg_id())) {
            throw new Exception('Agent Registration id is null.', Zend_Log::ERR);
        }
        $select = $this->getMapper()
            ->getDbTable()
            ->select()
            ->from('agent', 'agent_id')
            ->where('`agent_reg_id`= ?', $this->getAgent_reg_id());
        $id = $select->query()->fetchColumn();
        if (! $id) {
            throw new Exception(
            'Unable to retrieve agent id from registration id "' .
             $this->getAgent_reg_id() . '"', Zend_Log::ERR);
        }
        $this->setAgent_id($id);
        return $id;
    }
    protected function _fetchRegistrationId ()
    {
        if (is_null(self::getAgent_id())) {
            throw new Exception('Agent id is null.', Zend_Log::ERR);
        }
        $select = $this->getMapper()
            ->getDbTable()
            ->select()
            ->from('agent', 'agent_reg_id')
            ->where('`agent_id`= ?', $this->getAgent_id());
        $id = $select->query()->fetchColumn();
        if (! $id) {
            throw new Exception(
            'Unable to retrieve registration id from agent id "' .
             $this->getAgent_id() . '"', Zend_Log::ERR);
        }
        
        $this->setAgent_reg_id($id);
        return $id;
    }
    /*
     * @deprecated
    public function isValid ()
    {
        if (isset($this->_valid)) {
            return $this->_valid;
        } else {
            $sql = 'SELECT `agent_name` FROM `agent` WHERE (`agent_reg_id` = ?)';
            $bind = array($this->getAgent_id());
            $earnings = new Reale_Model_DbTable_Agent();
            $this->_valid = $earnings->getDefaultAdapter()
                ->query($sql, $bind)
                ->fetchColumn();
            if ($this->_valid) {
                return $this->_valid;
            } else {
                throw new Exception('The . "' . $this->getAgent_id() . '" is not a valid agent id.',Zend_Log::ERR);
            } 
        }
    }*/
    /**
     * 
     * This function fetches the upline of the agent.
     * $maxLevelsAbove => specifies number of entries that should be fetched.
     * By default the function will fetch all the entries upto root node.
     * 
     * The function will return the number of nodes required 
     * as per count variable and their relative level to the current node.
     * @param int $maxLevelsAbove
     * @return array
     * 
     */
    public function fetchUpline ($maxLevelsAbove = null)
    {
        $earnings = new Reale_Model_DbTable_AgentNetwork();
        $upperLevels = array($this->getAgent_id());
        $current = $this->getAgent_id();
        $levelsAbove = $maxLevelsAbove ? $maxLevelsAbove : 1;
        for ($levelNumber = 1; $levelNumber <= $levelsAbove; $levelNumber ++) {
            $current = $earnings->select()
                ->from($earnings->info('name'), 'sponsor_id')
                ->where('agent_id = ?', $current)
                ->query()
                ->fetchColumn();
            if ($current) {
                $upperLevels[] = $current;
                if (! $maxLevelsAbove) {
                    $levelsAbove ++;
                }
            } else {
                break;
            }
        }
        return $upperLevels;
    }
    public function fetchDownLine ($info = NULL, $maxDownLimit = 10)
    {
        $agent_id = $this->getAgent_id();
        return self::_fetchNetworkBelow($agent_id, $maxDownLimit, $info);
    }
    protected function _fetchNetworkBelow ($agent_id, $maxDownLimit = NULL, 
    $info = NULL)
    {
        if (isset($maxDownLimit)) {
            $maxDownLimit -= 1;
            if (- 1 == $maxDownLimit) {
                return null;
            }
        }
        $lowerNetwork = array();
        $children = self::_fetchJustBelow($agent_id, $info);
        $nodesBelow = count($children);
        /*$logger = Zend_Registry::get('logger');
        $logger->debug($children);*/
        if ($children) {
            foreach ($children as $key => $info) {
                if ($info) {
                    $lowerNetwork[$key]['net'] = self::_fetchNetworkBelow($key, 
                    $maxDownLimit, $info);
                    $lowerNetwork[$key]['info'] = $info;
                } else {
                    $lowerNetwork[$key] = self::_fetchNetworkBelow($key, 
                    $maxDownLimit, $info);
                }
            }
        } else {
            return null;
        }
        return $lowerNetwork;
    }
    protected function _fetchJustBelow ($agent_id, $info = NULL)
    {
        $earnings = new Reale_Model_DbTable_AgentNetwork();
        $select = $earnings->getAdapter()
            ->select()
            ->from($earnings->info('name'), 'agent_id')
            ->where('sponsor_id = ?', $agent_id);
        if ($info) {
            $select->join('agent', 'agent.agent_id = agent_network.agent_id', 
            'agent_reg_id');
            $select->columns(array('state' => 'activity_status_id'));
        }
        $children = $select->query()->fetchAll(Zend_Db::FETCH_UNIQUE);
        /*$logger = Zend_Registry::get('logger');
        $logger->debug($children);*/
        if (! count($children)) {
            return null;
        }
        return $children;
    }
    /**
     * 
     * Enter description here ...
     * @param unknown_type $upperLevels
     */
    public function networkStat ()
    {
        $network = self::fetchDownLine(null, null);
        self::array_depth($network);
        return $network;
    }
    protected function array_depth (&$network, $depth = NULL)
    {
        $depth = $depth ? $depth + 1 : 1;
        $nodeCount = count($network, true);
        $network["depth_$depth"] = $nodeCount;
        $keys = array_keys($network);
        foreach ($keys as $key) {
            if (is_array($network[$key])) {
                self::array_depth($network[$key], $depth);
            }
        }
    }
    /**
     * 
     *Disburse function performs the disbursements.
     *@param int $net_trans
     *@return bool
     *
     */
    public function disburse ($net_trans)
    {
        $upLine = $this->fetchUpline(self::MAX_UPLINE);
        $amount = self::AGENT_REG_FEES;
        $data = array('trans_id' => $net_trans, 'trans_type' => 'NETWORK');
        $nodeLevel = $this->fetchNodeLevel();
        $brokerage = ($nodeLevel >= 10) ? self::$_networkBrokerage['10']: self::$_networkBrokerage[$nodeLevel];       
        $netDisburse = ($brokerage * $amount) / 100;
        $leftAmount = $amount-$netDisburse;
        
        try { 
            $earnings = new Reale_Model_DbTable_AgentEarnings();
            $earnings->getAdapter()->beginTransaction();
            $agentRegister = new Reale_Model_DbTable_AgentRegister();
            $agentRegister->update(array('is_distributed' => 1), 
            "net_trans = $net_trans");

                $data['agent_id'] = $upLine[1];
                // Check if upline is root.
                if ($upLine[1] == self::ROOT_AGENT_ID) {
                    $data['amount'] = $amount;
                    $earnings->insert($data);
                    $earnings->getAdapter()->commit();
                    return true;
                }
                else{
                $agentShare = (15 * $amount) / 100;
                $data['amount'] = $agentShare;      		
                $earnings->insert($data);
                $netDisburse -= $agentShare;
            	}
            $check = 0;
            for($i=0;$i<count($upLine);$i++){
            	if($upLine[$i] == self::ROOT_AGENT_ID){
            		$check = 1;
            		break;
            	}
            }
            
            if($check == 1){
            	$leftUpline = count($upLine)-3;
            	$eachDisburse = $netDisburse/$leftUpline;	
            }
            else{
            	$leftUpline = count($upLine)-2;
            	$eachDisburse = $netDisburse/$leftUpline;
            }
            for ($i = 2; $i <= $leftUpline,$netDisburse>0; $i++){
            	if($upLine[$i] == self::ROOT_AGENT_ID ){
            		break;
            	}
                $data['agent_id'] = $upLine[$i];
                $data['amount'] = $eachDisburse;
                $netDisburse-=$eachDisburse;
                $earnings->insert($data);           	  	
           	}
           	$data['agent_id'] = self::ROOT_AGENT_ID;
           	$data['amount'] = $leftAmount;
           	$earnings->insert($data);
            $earnings->getAdapter()->commit();
          return true;
        } catch (Exception $e) {
            $earnings->getAdapter()->rollBack();
            throw $e;
        }
    }
    
    
    public function currentBusinessLevel ()
    {
        return self::_businessLevels(1);
    }
    public function businessLevels ()
    {
        return self::_businessLevels(null,true);
    }
    
    protected function _businessLevels ($currentOnly = NULL, $detail = NULL)
    {
        $achievement = new Reale_Model_DbTable_AgentAchievement();
        $level = $achievement->select()
            ->from($achievement->info('name'), 'business_level_no')
            ->where('agent_id = ?', $this->getAgent_id())
            ->order('business_level_no DESC');
        if ($currentOnly) {
            $level->limit(1);
        }
        if ($detail) {
            $level->columns(array('dated', 'prize'));
            return $level->query()->fetchAll();
        }
        
        $currentLevel = $level->query()->fetchColumn();
        $currentLevel = $currentLevel ? $currentLevel: 1;
        return $currentLevel;
    }
    
    
    public function networkLevel ()
    {
        /*
         * @todo Level of agent in network.(its not business level.)
         */
    }

	public function networkAccount ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchNetworkAccount($agent_id,'all',$dispatchDate,$transDate);
    }

	public function networkDispatched ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchNetworkAccount($agent_id,1,$dispatchDate,$transDate);
    }
    
	public function networkPending ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchNetworkAccount($agent_id,0,$dispatchDate,$transDate);
    }
    
	public function businessAccount ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchBusinessAccount($agent_id,'all',$dispatchDate,$transDate);
    }

	public function businessDispatched ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchBusinessAccount($agent_id,1,$dispatchDate,$transDate);
    }
    
	public function businessPending ($dispatchDate = NULL, $transDate = NULL)
    {
        $agent_id = $this->getAgent_id();
        return $this->getMapper()->fetchBusinessAccount($agent_id,0,$dispatchDate,$transDate);
    }
}


